package com.yuan.base.service.infrastructure;

import com.alibaba.fastjson.JSON;
import com.yuan.base.service.common.BaseContext;
import com.yuan.base.service.common.HeaderConstants;
import com.yuan.base.service.common.dto.AppInfo;
import com.yuan.base.service.common.dto.BusinessInfo;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.UUID;

/**
 * Application Mapped Information Context 应用映射信息上下文
 * @author lintiangang
 * @date 2021/03/25 17:52
 **/
@Slf4j
public class AMIC {
    public static void init(HttpServletRequest req) {
        noExceptionExec(() -> {
            String userIdStr = req.getHeader(HeaderConstants.USER_ID);
            if (!StringUtils.isEmpty(userIdStr)) {
                BaseContext.put(HeaderConstants.USER_ID, Long.valueOf(userIdStr));
                MDC.put(HeaderConstants.USER_ID, userIdStr);
            }
        });

        noExceptionExec(() -> {
            String infoStr = req.getHeader(HeaderConstants.APP_INFO);
            if (!StringUtils.isEmpty(infoStr)) {
                BaseContext.put(HeaderConstants.APP_INFO, JSON.parseObject(infoStr, AppInfo.class));
            }
        });

        noExceptionExec(() -> {
            String infoStr = req.getHeader(HeaderConstants.BUSINESS_INFO);
            if (!StringUtils.isEmpty(infoStr)) {
                BaseContext.put(HeaderConstants.BUSINESS_INFO, JSON.parseObject(infoStr, BusinessInfo.class));
            }
        });

        noExceptionExec(() -> {
            String traceId = req.getHeader(HeaderConstants.TRACE_ID);
            if (StringUtils.isEmpty(traceId)) {
                traceId = buildTraceId();
            }
            BaseContext.put(HeaderConstants.TRACE_ID, traceId);
            MDC.put(HeaderConstants.TRACE_ID, traceId);
        });
    }

    public static void clear() {
        BaseContext.clean();
        MDC.clear();
    }


    public static void setAppInfo(AppInfo appInfo) {
        if (appInfo != null) {
            BaseContext.put(HeaderConstants.APP_INFO, appInfo);
        }
    }

    public static void setBusinessInfo(BusinessInfo businessInfo) {
        if (businessInfo != null) {
            BaseContext.put(HeaderConstants.BUSINESS_INFO, businessInfo);
        }
    }

    public static void setUserId(Long userId) {
        if (userId != null) {
            BaseContext.put(HeaderConstants.USER_ID, userId);
        }
    }

    public static Long getUserId() {
        Object userId = BaseContext.get(HeaderConstants.USER_ID);
        return (Long) userId;
    }

    public static AppInfo getAppInfo() {
        return (AppInfo) BaseContext.get(HeaderConstants.APP_INFO);
    }

    public static BusinessInfo getBusinessInfo() {
        return (BusinessInfo) BaseContext.get(HeaderConstants.BUSINESS_INFO);
    }

    public static String getTraceId() {
        Object traceId = BaseContext.get(HeaderConstants.TRACE_ID);
        if (traceId == null) {
            traceId = buildTraceId();
        }
        return (String) traceId;
    }

    public static void setTraceId(String traceId) {
        BaseContext.put(HeaderConstants.TRACE_ID, traceId);
    }

    private static String buildTraceId() {
        String traceId = UUID.randomUUID().toString();
        setTraceId(traceId);
        return traceId;
    }


    public interface AFunction {
        void apply();
    }

    private static void noExceptionExec(AFunction function) {
        try {
            function.apply();
        } catch (Exception e) {
            log.error("转化异常", e);
        }
    }
}
